package com.sen.paydemo.controller;

import com.alibaba.fastjson.JSON;
import com.sen.paydemo.service.WxPayService;
import com.sen.paydemo.util.HttpUtils;
import com.sen.paydemo.util.WechatPay2ValidatorForRequest;
import com.sen.paydemo.vo.ApiResult;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 微信支付接口管理
 *
 * @作者: 韩宗森
 * @创建时间: 2024/1/9 19:07
 */
@Tag(name = "网站微信支付API")
@RestController
@RequestMapping("/api/wx-pay")
@Slf4j
public class WxPayController extends BaseController {

    @Resource
    private WxPayService wxPayService;

    @Resource
    private Verifier verifier;

    @Operation(summary = "调用统一下单API,生成支付二维码")
    @GetMapping("/native/{productId}")
    public ApiResult<?> nativePay(@PathVariable("productId") Integer productId) throws Exception {
        log.info("发起支付请求");

        // 返回支付二维码链接和订单号
        Map<String, Object> map = wxPayService.nativePay(productId);

        return success("测试成功" + new Date(), map);
    }

    @Operation(summary = "微信H5支付接口")
    @GetMapping("/h5/{productId}")
    public ApiResult<?> h5Pay(@PathVariable("productId") Integer productId, HttpServletRequest request) {
        log.info("发起支付请求");

        // 返回支付二维码链接和订单号
        Map<String, Object> map = wxPayService.h5Pay(productId);

        return success("测试成功" + new Date(), map);
    }

    /**
     * 回调通知
     * 文档地址
     * https://pay.weixin.qq.com/docs/merchant/apis/native-payment/payment-notice.html
     *
     * @param request
     * @param response
     * @return
     */
    @PostMapping("/native/notify")
    public String nativeNotify(HttpServletRequest request, HttpServletResponse response) {
        // 应答对象
        Map<String, String> map = new HashMap<>();

        try {
            // 处理通知参数
            String body = HttpUtils.readData(request);
            // 使用Fastjson 将 字符串转换为Map
            Map<String, Object> bodyMap = JSON.parseObject(body, HashMap.class);
            String requestId = (String) bodyMap.get("id");
            log.info("支付通知的id====> {}", requestId);
            log.info("支付通知的完整数据====> {}", body);

            //  签名的验证
            WechatPay2ValidatorForRequest wechatPay2ValidatorForRequest =
                    new WechatPay2ValidatorForRequest(verifier, requestId, body);

            // 验签不通过
            if (!wechatPay2ValidatorForRequest.validate(request)) {
                log.error("通知验签失败");
                // 失败应答
                response.setStatus(500);
                map.put("code", "ERROR");
                map.put("message", "通知验签失败");
                // 使用Fastjson将 Map转换为JSON 字符串
                return JSON.toJSONString(map);
            }
            log.info("通知验签成功");
            // 处理订单
            wxPayService.processOrder(bodyMap);
            // 成功应答
            response.setStatus(200);
            map.put("code", "SUCCESS");
            map.put("message", "成功");
            // 使用Fastjson将 Map转换为JSON 字符串
            return JSON.toJSONString(map);
        } catch (Exception e) {
            e.printStackTrace();
            // 失败应答
            response.setStatus(500);
            map.put("code", "ERROR");
            map.put("message", "失败");
            // 使用Fastjson将 Map转换为JSON 字符串
            return JSON.toJSONString(map);
        }
    }


    @Operation(summary = "用户取消订单")
    @PostMapping("/cancel/{orderNo}")
    public ApiResult<?> cancel(@PathVariable("orderNo") String orderNo) throws Exception {
        log.info("用户取消订单");
        wxPayService.cancelOrder(orderNo);

        return success("订单已取消");
    }

    @Operation(summary = "查询订单")
    @GetMapping("/query/{orderNo}")
    public ApiResult<?> queryOrder(@PathVariable("orderNo") String orderNo) throws Exception {
        log.info("查询订单");
        String result = wxPayService.queryOrder(orderNo);
        return success(result);
    }

    @Operation(summary = "申请退款")
    @PostMapping("/cancel/{orderNo}/{reason}")
    public ApiResult<?> cancel(@PathVariable("orderNo") String orderNo, @PathVariable("reason") String reason) throws Exception {
        log.info("申请退款");
        wxPayService.refund(orderNo, reason);

        return success("申请退款");
    }

    @Operation(summary = "查询退款:测试 ")
    @GetMapping("/query-refund/{refundNo}")
    public ApiResult<?> queryRefund(@PathVariable("refundNo") String refundNo) throws Exception {
        log.info("查询退款");
        String result = wxPayService.queryRefund(refundNo);
        return success(result);
    }

    /**
     * 回调通知
     * 退款结果通知
     * 文档地址 https://pay.weixin.qq.com/docs/merchant/apis/native-payment/payment-notice.html
     * 退款状态改变后,微信会把相关退款结果发给商户
     *
     * @param request
     * @param response
     * @return
     */
    @PostMapping("/refunds/notify")
    public String refundsNotify(HttpServletRequest request, HttpServletResponse response) {

        log.info("退款结果通知执行");
        // 应答对象
        Map<String, String> map = new HashMap<>();

        try {
            // 处理通知参数
            String body = HttpUtils.readData(request);
            // 使用Fastjson 将 字符串转换为Map
            Map<String, Object> bodyMap = JSON.parseObject(body, HashMap.class);
            String requestId = (String) bodyMap.get("id");
            log.info("支付通知的id====> {}", requestId);
            log.info("支付通知的完整数据====> {}", body);

            //  签名的验证
            WechatPay2ValidatorForRequest wechatPay2ValidatorForRequest =
                    new WechatPay2ValidatorForRequest(verifier, requestId, body);

            // 验签不通过
            if (!wechatPay2ValidatorForRequest.validate(request)) {
                log.error("通知验签失败");
                // 失败应答
                response.setStatus(500);
                map.put("code", "ERROR");
                map.put("message", "通知验签失败");
                // 使用Fastjson将 Map转换为JSON 字符串
                return JSON.toJSONString(map);
            }
            log.info("通知验签成功");
            // 处理退款单
            wxPayService.processRefund(bodyMap);
            // 成功应答
            response.setStatus(200);
            map.put("code", "SUCCESS");
            map.put("message", "成功");
            // 使用Fastjson将 Map转换为JSON 字符串
            return JSON.toJSONString(map);
        } catch (Exception e) {
            e.printStackTrace();
            // 失败应答
            response.setStatus(500);
            map.put("code", "ERROR");
            map.put("message", "失败");
            // 使用Fastjson将 Map转换为JSON 字符串
            return JSON.toJSONString(map);
        }
    }


    @Operation(summary = "获取账单url:测试 ")
    @GetMapping("/query-bill/{billDate}/{type}")
    public ApiResult<?> queryBill(@PathVariable("billDate") String billDate, @PathVariable("type") String type) throws Exception {
        log.info("获取账单url");
        String downloadUrl = wxPayService.queryBill(billDate,type);
        return success(downloadUrl);
    }


    @Operation(summary = "下载账单")
    @GetMapping("/query-bill/{billDate}/{type}")
    public ApiResult<?> downloadBill(@PathVariable("billDate") String billDate, @PathVariable("type") String type) throws Exception {
        log.info("下载账单");
        String result = wxPayService.downloadBill(billDate,type);
        return success(result);
    }
}
